{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# 04 大语言模型\n",
    "大型语言模型（LLM）是LangChain的核心组件。LangChain不提供自己的LLM，而是提供了一个标准接口，用于与许多不同的LLM进行交互。\n",
    "https://python.langchain.com/docs/modules/model_io/models/llms/\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "#设置代理\n",
    "import os\n",
    "os.environ['http_proxy'] = 'http://127.0.0.1:10809'\n",
    "os.environ['https_proxy'] = 'http://127.0.0.1:10809'"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T05:46:53.126655500Z",
     "start_time": "2023-08-22T05:46:53.109655900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "from langchain.llms import OpenAI\n",
    "llm = OpenAI()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:24:30.462793200Z",
     "start_time": "2023-08-22T03:24:30.437794700Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "使用 LLM 的最简单方法是可调用对象：传入字符串，获取字符串完成。\n",
    "```shell\n",
    "__call__: string in -> string out\n",
    "```\n",
    "这是他内部函数"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "'\\n\\n两个人在一起聊天，一个问另一个：\"你最近怎么样？\"\\n\\n另一个回答：\"我想像一根螺丝钉一样，拧得越来越紧！\"'"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#可以直接调用\n",
    "llm(\"给我讲一个笑话\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:25:42.574590400Z",
     "start_time": "2023-08-22T03:25:39.759421Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "generate: 批量调用，输出更丰富\n",
    "\n",
    "generate 允许您使用字符串列表调用模型，从而返回比文本更完整的响应。\n",
    "此完整响应可能包括多个热门响应和其他特定于LLM提供程序的信息："
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "llm_result = llm.generate([\"给我讲个笑话\", \"给我讲个诗词\"]*15)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:27:08.844560900Z",
     "start_time": "2023-08-22T03:26:57.761361500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "30"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(llm_result.generations)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:27:14.518626100Z",
     "start_time": "2023-08-22T03:27:14.509626300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "data": {
      "text/plain": "[Generation(text='\\n\\n笑话：\\n\\n一个男孩走进一家商店，问老板：“你有什么新鲜的东西卖吗？”\\n\\n老板回答：“有，我有一只新鲜的鸡！”\\n\\n男孩说：“太好了，我要买。你知道怎么把它变成鸭子吗？”\\n\\n老板说：“不知道，为什么？”\\n\\n男孩说：“因为我想给它一个惊喜！”', generation_info={'finish_reason': 'stop', 'logprobs': None})]"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm_result.generations[0]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:27:18.618856500Z",
     "start_time": "2023-08-22T03:27:18.596859900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "data": {
      "text/plain": "[Generation(text='\\n\\n《春晓》\\n\\n春眠不觉晓，\\n处处闻啼鸟。\\n夜来风雨声，\\n花落知多少。', generation_info={'finish_reason': 'stop', 'logprobs': None})]"
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm_result.generations[1]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:27:53.282793400Z",
     "start_time": "2023-08-22T03:27:53.232783300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "data": {
      "text/plain": "[Generation(text='\\n\\n一个猴子去拜访朋友，准备给他带礼物，但是他不知道该带什么，于是他就想：“现在是冬天，我可以带一件厚厚的毛衣给他！”于是他就带了毛衣去拜访朋友，朋友很开心，问猴子：“你怎么知道我需要一件毛衣呢？”猴子说：“因为这是猴子送人的冬衣！”', generation_info={'finish_reason': 'stop', 'logprobs': None})]"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm_result.generations[2]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:28:04.128493300Z",
     "start_time": "2023-08-22T03:28:04.058869400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "data": {
      "text/plain": "[Generation(text='\\n\\n春晓\\n\\n孟浩然\\n\\n春眠不觉晓，\\n\\n处处闻啼鸟。\\n\\n夜来风雨声，\\n\\n花落知多少。', generation_info={'finish_reason': 'stop', 'logprobs': None})]"
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm_result.generations[3]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:28:08.461815Z",
     "start_time": "2023-08-22T03:28:08.441814800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "data": {
      "text/plain": "{'token_usage': {'total_tokens': 4236,\n  'prompt_tokens': 435,\n  'completion_tokens': 3801},\n 'model_name': 'text-davinci-003'}"
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#您还可以访问返回的提供程序特定信息。此信息在提供商之间没有标准化。\n",
    "llm_result.llm_output"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:28:39.561663400Z",
     "start_time": "2023-08-22T03:28:39.544660200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.1 异步接口\n",
    "LangChain通过利用asyncio库为LLM提供异步支持。\n",
    "异步支持对于同时调用多个 LLM 特别有用，因为这些调用是网络绑定的。\n",
    "目前、 OpenAI PromptLayerOpenAI ChatOpenAI 、 Anthropic 和 Cohere 受支持，但对其他 LLM 的异步支持已在路线图上。\n",
    "您可以使用该方法 agenerate 异步调用 OpenAI LLM。\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [],
   "source": [
    "import openai\n",
    "openai.proxy = os.getenv('https_proxy')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T05:47:06.538233200Z",
     "start_time": "2023-08-22T05:47:06.520234500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "# 导入所需的模块\n",
    "import time  # 用于计时\n",
    "import asyncio  # 用于处理异步编程\n",
    "\n",
    "from langchain.llms import OpenAI  # 从langchain.llms库导入OpenAI类\n",
    "\n",
    "# 定义一个串行（同步）方式生成文本的函数\n",
    "def generate_serially():\n",
    "    llm = OpenAI(temperature=0.9)  # 创建OpenAI对象，并设置temperature参数为0.9\n",
    "    for _ in range(10):  # 循环10次\n",
    "        resp = llm.generate([\"Hello, how are you?\"])  # 调用generate方法生成文本\n",
    "        print(resp.generations[0][0].text)  # 打印生成的文本\n",
    "\n",
    "# 定义一个异步生成文本的函数\n",
    "async def async_generate(llm):\n",
    "    resp = await llm.agenerate([\"Hello, how are you?\"])  # 异步调用agenerate方法生成文本\n",
    "    print(resp.generations[0][0].text)  # 打印生成的文本\n",
    "\n",
    "# 定义一个并发（异步）方式生成文本的函数\n",
    "async def generate_concurrently():\n",
    "    llm = OpenAI(temperature=0.9)  # 创建OpenAI对象，并设置temperature参数为0.9\n",
    "    tasks = [async_generate(llm) for _ in range(10)]  # 创建10个异步任务\n",
    "    await asyncio.gather(*tasks)  # 使用asyncio.gather等待所有异步任务完成\n",
    "\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T05:47:10.118831500Z",
     "start_time": "2023-08-22T05:47:07.863159600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, how about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing good, thanks! How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you for asking! How about yourself?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thanks for asking! How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\u001B[1mConcurrent executed in 2.14 seconds.\u001B[0m\n"
     ]
    }
   ],
   "source": [
    "# 记录当前时间点\n",
    "s = time.perf_counter()\n",
    "# 使用异步方式并发执行生成文本的任务\n",
    "# 如果在Jupyter以外运行此代码，使用 asyncio.run(generate_concurrently())\n",
    "await generate_concurrently()\n",
    "# 计算并发执行所花费的时间\n",
    "elapsed = time.perf_counter() - s\n",
    "print(\"\\033[1m\" + f\"Concurrent executed in {elapsed:0.2f} seconds.\" + \"\\033[0m\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T05:47:13.611147200Z",
     "start_time": "2023-08-22T05:47:11.465602300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\n",
      "\n",
      "I'm good, thanks! How about you?\n",
      "\n",
      "\n",
      "I'm doing well. How about you?\n",
      "\n",
      "\n",
      "I'm doing great. How about you?\n",
      "\n",
      "\n",
      "I'm doing well, thank you. How about you?\n",
      "\u001B[1mSerial executed in 12.38 seconds.\u001B[0m\n"
     ]
    }
   ],
   "source": [
    "# 记录当前时间点\n",
    "s = time.perf_counter()\n",
    "# 使用同步方式串行执行生成文本的任务\n",
    "generate_serially()\n",
    "# 计算串行执行所花费的时间\n",
    "elapsed = time.perf_counter() - s\n",
    "print(\"\\033[1m\" + f\"Serial executed in {elapsed:0.2f} seconds.\" + \"\\033[0m\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T03:55:39.894316100Z",
     "start_time": "2023-08-22T03:55:27.513964Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.2 定制大语言模型\n",
    "如果您想使用自己的 LLM 或与 LangChain 中支持的包装器不同的包装器。\n",
    "自定义LLM只需要实现一件必需的事情：\n",
    "\n",
    "一个 _call 方法，它接受一个字符串、一些可选的非索引字，并返回一个字符串\n",
    "\n",
    "它可以实现第二个可选的东西：\n",
    "\n",
    "用于帮助打印此类 _identifying_params 的属性。应该返回字典。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [],
   "source": [
    "# 让我们实现一个非常简单的自定义 LLM，它只返回输入的前 N 个字符。\n",
    "from typing import Any, List, Mapping, Optional\n",
    "from langchain.callbacks.manager import CallbackManagerForLLMRun\n",
    "from langchain.llms.base import LLM\n",
    "\n",
    "#这个类 CustomLLM 继承了 LLM 类，并增加了一个新的类变量 n。\n",
    "#有两个 property 装饰的方法，分别是 _llm_type 和 _identifying_params，这两个方法都返回一些固定的属性值。\n",
    "#_call 方法主要是对输入的 prompt 字符串进行处理，返回前 n 个字符。如果提供了 stop 参数，它将引发一个异常。\n",
    "\n",
    "\n",
    "# 继承自 LLM 的 CustomLLM 类\n",
    "class CustomLLM1(LLM):\n",
    "\n",
    "    # 类变量，表示一个整数\n",
    "    n: int\n",
    "\n",
    "    # 一个属性装饰器，用于获取 _llm_type 的值\n",
    "    @property\n",
    "    def _llm_type(self) -> str:\n",
    "        # 返回 \"custom\" 字符串作为 _llm_type 的值\n",
    "        return \"custom\"\n",
    "\n",
    "    # _call 方法用于处理某些操作\n",
    "    def _call(\n",
    "        self,\n",
    "        prompt: str,  # 输入的提示字符串\n",
    "        stop: Optional[List[str]] = None,  # 可选的停止字符串列表，默认为 None\n",
    "        run_manager: Optional[CallbackManagerForLLMRun] = None,  # 可选的回调管理器，默认为 None\n",
    "    ) -> str:\n",
    "        # 如果 stop 参数不为 None，则抛出 ValueError 异常\n",
    "        if stop is not None:\n",
    "            raise ValueError(\"stop kwargs are not permitted.\")\n",
    "        # 返回 prompt 字符串的前 n 个字符\n",
    "        return prompt[: self.n]\n",
    "\n",
    "    # 一个属性装饰器，用于获取 _identifying_params 的值\n",
    "    @property\n",
    "    def _identifying_params(self) -> Mapping[str, Any]:\n",
    "        # 这个方法的文档字符串，说明这个方法的功能是获取标识参数\n",
    "        \"\"\"Get the identifying parameters.\"\"\"\n",
    "        # 返回一个字典，包含 n 的值\n",
    "        return {\"n\": self.n}\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T06:12:48.312119300Z",
     "start_time": "2023-08-22T06:12:48.274115500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [],
   "source": [
    "llm = CustomLLM1(n=10)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T06:12:51.568591800Z",
     "start_time": "2023-08-22T06:12:51.554553700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "data": {
      "text/plain": "'This is a '"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm(\"This is a foobar thing\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T06:12:52.150794600Z",
     "start_time": "2023-08-22T06:12:52.136786400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001B[1mCustomLLM1\u001B[0m\n",
      "Params: {'n': 10}\n"
     ]
    }
   ],
   "source": [
    "print(llm)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-22T06:12:52.666683700Z",
     "start_time": "2023-08-22T06:12:52.620142500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.3假的大语言模型\n",
    "有时，您可能希望使用一个假的LLM，它只是返回输入的字符串。\n",
    "这对于测试或调试非常有用，因为它允许您在不使用真实LLM的情况下测试您的代码。\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3mAction: Python REPL\n",
      "Action Input: print(2 + 2)\u001B[0m\n",
      "Observation: Python REPL is not a valid tool, try another one.\n",
      "Thought:\u001B[32;1m\u001B[1;3mFinal Answer: 4\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": "'4'"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 从langchain.llms.fake模块导入FakeListLLM类，此类可能用于模拟或伪造某种行为\n",
    "from langchain.llms.fake import FakeListLLM\n",
    "\n",
    "# 从langchain.agents模块导入load_tools、initialize_agent和AgentType\n",
    "from langchain.agents import load_tools\n",
    "from langchain.agents import initialize_agent\n",
    "from langchain.agents import AgentType\n",
    "\n",
    "# 调用load_tools函数，加载名为\"python_repl\"的工具\n",
    "tools = load_tools([\"python_repl\"])\n",
    "\n",
    "# 定义一个响应列表，这些响应可能是模拟LLM的预期响应\n",
    "responses = [\"Action: Python REPL\\nAction Input: print(2 + 2)\", \"Final Answer: 4\"]\n",
    "\n",
    "# 使用上面定义的responses初始化一个FakeListLLM对象\n",
    "llm = FakeListLLM(responses=responses)\n",
    "\n",
    "# 调用initialize_agent函数，使用上面的tools和llm，以及指定的代理类型和verbose参数来初始化一个代理\n",
    "agent = initialize_agent(\n",
    "    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
    ")\n",
    "\n",
    "# 调用代理的run方法，传递字符串\"whats 2 + 2\"作为输入，询问代理2加2的结果\n",
    "agent.run(\"whats 2 + 2\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T08:25:49.688647100Z",
     "start_time": "2023-08-24T08:25:49.623423800Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "与假的LLM类似，LangChain提供了一个伪LLM类，可用于测试，调试或教育目的。\n",
    "这允许您模拟对LLM的呼叫，并模拟人类在收到提示时将如何响应。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting wikipedia\n",
      "  Using cached wikipedia-1.4.0.tar.gz (27 kB)\n",
      "  Preparing metadata (setup.py): started\n",
      "  Preparing metadata (setup.py): finished with status 'done'\n",
      "Requirement already satisfied: beautifulsoup4 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from wikipedia) (4.12.2)\n",
      "Requirement already satisfied: requests<3.0.0,>=2.0.0 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from wikipedia) (2.31.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (2023.7.22)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (3.2.0)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (2.0.4)\n",
      "Requirement already satisfied: idna<4,>=2.5 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from requests<3.0.0,>=2.0.0->wikipedia) (3.4)\n",
      "Requirement already satisfied: soupsieve>1.2 in e:\\pycharmproject\\langchainstudyproject\\venv\\lib\\site-packages (from beautifulsoup4->wikipedia) (2.4.1)\n",
      "Building wheels for collected packages: wikipedia\n",
      "  Building wheel for wikipedia (setup.py): started\n",
      "  Building wheel for wikipedia (setup.py): finished with status 'done'\n",
      "  Created wheel for wikipedia: filename=wikipedia-1.4.0-py3-none-any.whl size=11707 sha256=8d815f24833c9e74fa8e641a8a13d04aca7e24f9444a6647cd112c708a1f592d\n",
      "  Stored in directory: c:\\users\\lenovo\\appdata\\local\\pip\\cache\\wheels\\b2\\7f\\26\\524faff9145e274da278dc97d63ab0bfde1f791ecf101a9c95\n",
      "Successfully built wikipedia\n",
      "Installing collected packages: wikipedia\n",
      "Successfully installed wikipedia-1.4.0\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "[notice] A new release of pip available: 22.3.1 -> 23.2.1\n",
      "[notice] To update, run: python.exe -m pip install --upgrade pip\n"
     ]
    }
   ],
   "source": [
    "! pip install wikipedia"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T08:27:00.361073200Z",
     "start_time": "2023-08-24T08:26:48.341573200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "#设置代理\n",
    "import os\n",
    "os.environ['http_proxy'] = 'http://127.0.0.1:10809'\n",
    "os.environ['https_proxy'] = 'http://127.0.0.1:10809'"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T08:27:19.280209800Z",
     "start_time": "2023-08-24T08:27:19.259228800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\n",
      "===PROMPT====\n",
      "Answer the following questions as best you can. You have access to the following tools:\n",
      "\n",
      "Wikipedia: A wrapper around Wikipedia. Useful for when you need to answer general questions about people, places, companies, facts, historical events, or other subjects. Input should be a search query.\n",
      "\n",
      "Use the following format:\n",
      "\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take, should be one of [Wikipedia]\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "\n",
      "Question: What is 'Bocchi the Rock!'?\n",
      "Thought:\n",
      "=====END OF PROMPT======\n"
     ]
    },
    {
     "ename": "OutputParserException",
     "evalue": "Parsing LLM output produced both a final answer and a parse-able action:: I need to use a tool.     Action: Wikipedia     Action Input: Bocchi the Rock!, Japanese four-panel manga and anime series.     Observation: Page: Bocchi the Rock!     Summary: Bocchi the Rock! (ぼっち・ざ・ろっく!, Bocchi Za Rokku!) is a Japanese four-panel manga series written and illustrated by Aki Hamaji. It has been serialized in Houbunsha's seinen manga magazine Manga Time Kirara Max since December 2017. Its chapters have been collected in five tankōbon volumes as of November 2022.     An anime television series adaptation produced by CloverWorks aired from October to December 2022. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.          Page: Manga Time Kirara     Summary: Manga Time Kirara (まんがタイムきらら, Manga Taimu Kirara) is a Japanese seinen manga magazine published by Houbunsha which mainly serializes four-panel manga. The magazine is sold on the ninth of each month and was first published as a special edition of Manga Time, another Houbunsha magazine, on May 17, 2002. Characters from this magazine have appeared in a crossover role-playing game called Kirara Fantasia.          Page: Manga Time Kirara Max     Summary: Manga Time Kirara Max (まんがタイムきららMAX) is a Japanese four-panel seinen manga magazine published by Houbunsha. It is the third magazine of the \"Kirara\" series, after \"Manga Time Kirara\" and \"Manga Time Kirara Carat\". The first issue was released on September 29, 2004. Currently the magazine is released on the 19th of each month.     Thought:\nThese are not relevant articles.     Action: Wikipedia     Action Input: Bocchi the Rock!, Japanese four-panel manga series written and illustrated by Aki Hamaji.     Observation: Page: Bocchi the Rock!     Summary: Bocchi the Rock! (ぼっち・ざ・ろっく!, Bocchi Za Rokku!) is a Japanese four-panel manga series written and illustrated by Aki Hamaji. It has been serialized in Houbunsha's seinen manga magazine Manga Time Kirara Max since December 2017. Its chapters have been collected in five tankōbon volumes as of November 2022.     An anime television series adaptation produced by CloverWorks aired from October to December 2022. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.     Thought:\nIt worked.\nFinal Answer: Bocchi the Rock! is a four-panel manga series and anime television series. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.\n> Finished chain.",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mOutputParserException\u001B[0m                     Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[10], line 25\u001B[0m\n\u001B[0;32m     20\u001B[0m agent \u001B[38;5;241m=\u001B[39m initialize_agent(\n\u001B[0;32m     21\u001B[0m     tools, llm, agent\u001B[38;5;241m=\u001B[39mAgentType\u001B[38;5;241m.\u001B[39mZERO_SHOT_REACT_DESCRIPTION, verbose\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m\n\u001B[0;32m     22\u001B[0m )\n\u001B[0;32m     24\u001B[0m \u001B[38;5;66;03m# 调用代理的run方法，传递字符串\"What is 'Bocchi the Rock!'?\"作为输入，询问代理关于'Bocchi the Rock!'的信息\u001B[39;00m\n\u001B[1;32m---> 25\u001B[0m \u001B[43magent\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrun\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mWhat is \u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mBocchi the Rock!\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m?\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\chains\\base.py:451\u001B[0m, in \u001B[0;36mChain.run\u001B[1;34m(self, callbacks, tags, metadata, *args, **kwargs)\u001B[0m\n\u001B[0;32m    449\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mlen\u001B[39m(args) \u001B[38;5;241m!=\u001B[39m \u001B[38;5;241m1\u001B[39m:\n\u001B[0;32m    450\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m`run` supports only one positional argument.\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m--> 451\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43margs\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;241;43m0\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcallbacks\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mcallbacks\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtags\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mtags\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mmetadata\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mmetadata\u001B[49m\u001B[43m)\u001B[49m[\n\u001B[0;32m    452\u001B[0m         _output_key\n\u001B[0;32m    453\u001B[0m     ]\n\u001B[0;32m    455\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m kwargs \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m args:\n\u001B[0;32m    456\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m(kwargs, callbacks\u001B[38;5;241m=\u001B[39mcallbacks, tags\u001B[38;5;241m=\u001B[39mtags, metadata\u001B[38;5;241m=\u001B[39mmetadata)[\n\u001B[0;32m    457\u001B[0m         _output_key\n\u001B[0;32m    458\u001B[0m     ]\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\chains\\base.py:258\u001B[0m, in \u001B[0;36mChain.__call__\u001B[1;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001B[0m\n\u001B[0;32m    256\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m (\u001B[38;5;167;01mKeyboardInterrupt\u001B[39;00m, \u001B[38;5;167;01mException\u001B[39;00m) \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[0;32m    257\u001B[0m     run_manager\u001B[38;5;241m.\u001B[39mon_chain_error(e)\n\u001B[1;32m--> 258\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[0;32m    259\u001B[0m run_manager\u001B[38;5;241m.\u001B[39mon_chain_end(outputs)\n\u001B[0;32m    260\u001B[0m final_outputs: Dict[\u001B[38;5;28mstr\u001B[39m, Any] \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mprep_outputs(\n\u001B[0;32m    261\u001B[0m     inputs, outputs, return_only_outputs\n\u001B[0;32m    262\u001B[0m )\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\chains\\base.py:252\u001B[0m, in \u001B[0;36mChain.__call__\u001B[1;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001B[0m\n\u001B[0;32m    246\u001B[0m run_manager \u001B[38;5;241m=\u001B[39m callback_manager\u001B[38;5;241m.\u001B[39mon_chain_start(\n\u001B[0;32m    247\u001B[0m     dumpd(\u001B[38;5;28mself\u001B[39m),\n\u001B[0;32m    248\u001B[0m     inputs,\n\u001B[0;32m    249\u001B[0m )\n\u001B[0;32m    250\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m    251\u001B[0m     outputs \u001B[38;5;241m=\u001B[39m (\n\u001B[1;32m--> 252\u001B[0m         \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_call\u001B[49m\u001B[43m(\u001B[49m\u001B[43minputs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mrun_manager\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mrun_manager\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m    253\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m new_arg_supported\n\u001B[0;32m    254\u001B[0m         \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_call(inputs)\n\u001B[0;32m    255\u001B[0m     )\n\u001B[0;32m    256\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m (\u001B[38;5;167;01mKeyboardInterrupt\u001B[39;00m, \u001B[38;5;167;01mException\u001B[39;00m) \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[0;32m    257\u001B[0m     run_manager\u001B[38;5;241m.\u001B[39mon_chain_error(e)\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\agents\\agent.py:1029\u001B[0m, in \u001B[0;36mAgentExecutor._call\u001B[1;34m(self, inputs, run_manager)\u001B[0m\n\u001B[0;32m   1027\u001B[0m \u001B[38;5;66;03m# We now enter the agent loop (until it returns something).\u001B[39;00m\n\u001B[0;32m   1028\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_should_continue(iterations, time_elapsed):\n\u001B[1;32m-> 1029\u001B[0m     next_step_output \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_take_next_step\u001B[49m\u001B[43m(\u001B[49m\n\u001B[0;32m   1030\u001B[0m \u001B[43m        \u001B[49m\u001B[43mname_to_tool_map\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1031\u001B[0m \u001B[43m        \u001B[49m\u001B[43mcolor_mapping\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1032\u001B[0m \u001B[43m        \u001B[49m\u001B[43minputs\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1033\u001B[0m \u001B[43m        \u001B[49m\u001B[43mintermediate_steps\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1034\u001B[0m \u001B[43m        \u001B[49m\u001B[43mrun_manager\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mrun_manager\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1035\u001B[0m \u001B[43m    \u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m   1036\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(next_step_output, AgentFinish):\n\u001B[0;32m   1037\u001B[0m         \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_return(\n\u001B[0;32m   1038\u001B[0m             next_step_output, intermediate_steps, run_manager\u001B[38;5;241m=\u001B[39mrun_manager\n\u001B[0;32m   1039\u001B[0m         )\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\agents\\agent.py:843\u001B[0m, in \u001B[0;36mAgentExecutor._take_next_step\u001B[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001B[0m\n\u001B[0;32m    841\u001B[0m     raise_error \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mFalse\u001B[39;00m\n\u001B[0;32m    842\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m raise_error:\n\u001B[1;32m--> 843\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[0;32m    844\u001B[0m text \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mstr\u001B[39m(e)\n\u001B[0;32m    845\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mhandle_parsing_errors, \u001B[38;5;28mbool\u001B[39m):\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\agents\\agent.py:832\u001B[0m, in \u001B[0;36mAgentExecutor._take_next_step\u001B[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001B[0m\n\u001B[0;32m    829\u001B[0m     intermediate_steps \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_prepare_intermediate_steps(intermediate_steps)\n\u001B[0;32m    831\u001B[0m     \u001B[38;5;66;03m# Call the LLM to see what to do.\u001B[39;00m\n\u001B[1;32m--> 832\u001B[0m     output \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39magent\u001B[38;5;241m.\u001B[39mplan(\n\u001B[0;32m    833\u001B[0m         intermediate_steps,\n\u001B[0;32m    834\u001B[0m         callbacks\u001B[38;5;241m=\u001B[39mrun_manager\u001B[38;5;241m.\u001B[39mget_child() \u001B[38;5;28;01mif\u001B[39;00m run_manager \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[0;32m    835\u001B[0m         \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39minputs,\n\u001B[0;32m    836\u001B[0m     )\n\u001B[0;32m    837\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m OutputParserException \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[0;32m    838\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mhandle_parsing_errors, \u001B[38;5;28mbool\u001B[39m):\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\agents\\agent.py:457\u001B[0m, in \u001B[0;36mAgent.plan\u001B[1;34m(self, intermediate_steps, callbacks, **kwargs)\u001B[0m\n\u001B[0;32m    455\u001B[0m full_inputs \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mget_full_inputs(intermediate_steps, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[0;32m    456\u001B[0m full_output \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mllm_chain\u001B[38;5;241m.\u001B[39mpredict(callbacks\u001B[38;5;241m=\u001B[39mcallbacks, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mfull_inputs)\n\u001B[1;32m--> 457\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43moutput_parser\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mparse\u001B[49m\u001B[43m(\u001B[49m\u001B[43mfull_output\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\agents\\mrkl\\output_parser.py:34\u001B[0m, in \u001B[0;36mMRKLOutputParser.parse\u001B[1;34m(self, text)\u001B[0m\n\u001B[0;32m     32\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m action_match:\n\u001B[0;32m     33\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m includes_answer:\n\u001B[1;32m---> 34\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m OutputParserException(\n\u001B[0;32m     35\u001B[0m             \u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;132;01m{\u001B[39;00mFINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mtext\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m\"\u001B[39m\n\u001B[0;32m     36\u001B[0m         )\n\u001B[0;32m     37\u001B[0m     action \u001B[38;5;241m=\u001B[39m action_match\u001B[38;5;241m.\u001B[39mgroup(\u001B[38;5;241m1\u001B[39m)\u001B[38;5;241m.\u001B[39mstrip()\n\u001B[0;32m     38\u001B[0m     action_input \u001B[38;5;241m=\u001B[39m action_match\u001B[38;5;241m.\u001B[39mgroup(\u001B[38;5;241m2\u001B[39m)\n",
      "\u001B[1;31mOutputParserException\u001B[0m: Parsing LLM output produced both a final answer and a parse-able action:: I need to use a tool.     Action: Wikipedia     Action Input: Bocchi the Rock!, Japanese four-panel manga and anime series.     Observation: Page: Bocchi the Rock!     Summary: Bocchi the Rock! (ぼっち・ざ・ろっく!, Bocchi Za Rokku!) is a Japanese four-panel manga series written and illustrated by Aki Hamaji. It has been serialized in Houbunsha's seinen manga magazine Manga Time Kirara Max since December 2017. Its chapters have been collected in five tankōbon volumes as of November 2022.     An anime television series adaptation produced by CloverWorks aired from October to December 2022. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.          Page: Manga Time Kirara     Summary: Manga Time Kirara (まんがタイムきらら, Manga Taimu Kirara) is a Japanese seinen manga magazine published by Houbunsha which mainly serializes four-panel manga. The magazine is sold on the ninth of each month and was first published as a special edition of Manga Time, another Houbunsha magazine, on May 17, 2002. Characters from this magazine have appeared in a crossover role-playing game called Kirara Fantasia.          Page: Manga Time Kirara Max     Summary: Manga Time Kirara Max (まんがタイムきららMAX) is a Japanese four-panel seinen manga magazine published by Houbunsha. It is the third magazine of the \"Kirara\" series, after \"Manga Time Kirara\" and \"Manga Time Kirara Carat\". The first issue was released on September 29, 2004. Currently the magazine is released on the 19th of each month.     Thought:\nThese are not relevant articles.     Action: Wikipedia     Action Input: Bocchi the Rock!, Japanese four-panel manga series written and illustrated by Aki Hamaji.     Observation: Page: Bocchi the Rock!     Summary: Bocchi the Rock! (ぼっち・ざ・ろっく!, Bocchi Za Rokku!) is a Japanese four-panel manga series written and illustrated by Aki Hamaji. It has been serialized in Houbunsha's seinen manga magazine Manga Time Kirara Max since December 2017. Its chapters have been collected in five tankōbon volumes as of November 2022.     An anime television series adaptation produced by CloverWorks aired from October to December 2022. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.     Thought:\nIt worked.\nFinal Answer: Bocchi the Rock! is a four-panel manga series and anime television series. The series has been praised for its writing, comedy, characters, and depiction of social anxiety, with the anime's visual creativity receiving acclaim.\n> Finished chain."
     ]
    }
   ],
   "source": [
    "# 从langchain.llms.human模块导入HumanInputLLM类，此类可能允许人类输入或交互来模拟LLM的行为\n",
    "from langchain.llms.human import HumanInputLLM\n",
    "\n",
    "# 从langchain.agents模块导入load_tools、initialize_agent和AgentType\n",
    "from langchain.agents import load_tools\n",
    "from langchain.agents import initialize_agent\n",
    "from langchain.agents import AgentType\n",
    "\n",
    "# 调用load_tools函数，加载名为\"wikipedia\"的工具\n",
    "tools = load_tools([\"wikipedia\"])\n",
    "\n",
    "# 初始化一个HumanInputLLM对象，其中prompt_func是一个函数，用于打印提示信息\n",
    "llm = HumanInputLLM(\n",
    "    prompt_func=lambda prompt: print(\n",
    "        f\"\\n===PROMPT====\\n{prompt}\\n=====END OF PROMPT======\"\n",
    "    )\n",
    ")\n",
    "\n",
    "# 调用initialize_agent函数，使用上面的tools和llm，以及指定的代理类型和verbose参数来初始化一个代理\n",
    "agent = initialize_agent(\n",
    "    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
    ")\n",
    "\n",
    "# 调用代理的run方法，传递字符串\"What is 'Bocchi the Rock!'?\"作为输入，询问代理关于'Bocchi the Rock!'的信息\n",
    "agent.run(\"What is 'Bocchi the Rock!'?\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T10:41:29.287801Z",
     "start_time": "2023-08-24T10:39:58.925831600Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.5 大语言模型的缓存\n",
    "\n",
    "LangChain为LLM提供了一个可选的缓存层。这很有用，原因有两个：\n",
    "\n",
    "如果您经常多次请求相同的完成，它可以通过减少您对 LLM 提供程序进行的 API 调用次数来节省您的资金。它可以通过减少您对LLM提供程序进行的API调用次数来加速您的应用程序。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Why did the chicken cross the road?\n",
      "\n",
      "To get to the other side!\n",
      "Predict method took 1.1823 seconds to execute.\n"
     ]
    }
   ],
   "source": [
    "#在内存缓存中\n",
    "import langchain\n",
    "from langchain.llms import OpenAI\n",
    "import time\n",
    "# To make the caching really obvious, lets use a slower model.\n",
    "llm = OpenAI(model_name=\"text-davinci-002\", n=2, best_of=2)\n",
    "from langchain.cache import InMemoryCache\n",
    "langchain.llm_cache = InMemoryCache()\n",
    "\n",
    "start_time = time.time()  # 记录开始时间\n",
    "# The first time, it is not yet in cache, so it should take longer\n",
    "print(llm.predict(\"Tell me a joke\"))\n",
    "end_time = time.time()  # 记录结束时间\n",
    "elapsed_time = end_time - start_time  # 计算总时间\n",
    "print(f\"Predict method took {elapsed_time:.4f} seconds to execute.\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T10:48:33.804358200Z",
     "start_time": "2023-08-24T10:48:32.615574600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Why did the chicken cross the road?\n",
      "\n",
      "To get to the other side!\n",
      "Predict method took 0.0000 seconds to execute.\n"
     ]
    }
   ],
   "source": [
    "start_time = time.time()  # 记录开始时间\n",
    "# The second time it is, so it goes faster\n",
    "print(llm.predict(\"Tell me a joke\"))\n",
    "end_time = time.time()  # 记录结束时间\n",
    "elapsed_time = end_time - start_time  # 计算总时间\n",
    "print(f\"Predict method took {elapsed_time:.4f} seconds to execute.\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T10:48:58.186818Z",
     "start_time": "2023-08-24T10:48:58.166821700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "今天，我在公司附近的商场买了一件新衣服。我觉得自己很漂亮，所以我决定去买一杯咖啡。我坐下来点了一杯咖啡，一个英俊的年轻人走过来坐在我对面。他给了我一个微笑，我微笑着回答他。我们聊了一会儿，然后他问我：“你要不要和我一起去看电影？”我说：“\n",
      "Predict method took 3.7383 seconds to execute.\n"
     ]
    }
   ],
   "source": [
    "# 使用SQLite数据库缓存\n",
    "# We can do the same thing with a SQLite cache\n",
    "from langchain.cache import SQLiteCache\n",
    "langchain.llm_cache = SQLiteCache(database_path=\".langchain.db\")\n",
    "\n",
    "\n",
    "start_time = time.time()  # 记录开始时间\n",
    "# The first time, it is not yet in cache, so it should take longer\n",
    "print(llm.predict(\"用中文讲个笑话\"))\n",
    "end_time = time.time()  # 记录结束时间\n",
    "elapsed_time = end_time - start_time  # 计算总时间\n",
    "print(f\"Predict method took {elapsed_time:.4f} seconds to execute.\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T10:52:11.515696100Z",
     "start_time": "2023-08-24T10:52:07.765896200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "今天，我在公司附近的商场买了一件新衣服。我觉得自己很漂亮，所以我决定去买一杯咖啡。我坐下来点了一杯咖啡，一个英俊的年轻人走过来坐在我对面。他给了我一个微笑，我微笑着回答他。我们聊了一会儿，然后他问我：“你要不要和我一起去看电影？”我说：“\n",
      "Predict method took 0.0030 seconds to execute.\n"
     ]
    }
   ],
   "source": [
    "start_time = time.time()  # 记录开始时间\n",
    "# The second time it is, so it goes faster\n",
    "print(llm.predict(\"用中文讲个笑话\"))\n",
    "end_time = time.time()  # 记录结束时间\n",
    "elapsed_time = end_time - start_time  # 计算总时间\n",
    "print(f\"Predict method took {elapsed_time:.4f} seconds to execute.\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T10:52:23.305261600Z",
     "start_time": "2023-08-24T10:52:23.279533300Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.6 大语言模型的序列化配置\n",
    "LangChain提供了一个方便的方法，用于将LLM的配置序列化为JSON字符串，以便将其保存到磁盘上的文件中。\n",
    "\n",
    "LLM 配置写入磁盘和从磁盘读取 LLM 配置。如果要保存给定LLM的配置（例如，提供程序，温度等），这将非常有用。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [],
   "source": [
    "from langchain.llms import OpenAI\n",
    "from langchain.llms.loading import load_llm\n",
    "llm = load_llm(\"llmstore/llm.json\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:07:25.896471300Z",
     "start_time": "2023-08-24T12:07:25.851364300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "data": {
      "text/plain": "OpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, client=<class 'openai.api_resources.completion.Completion'>, model_name='text-davinci-003', temperature=0.7, max_tokens=256, top_p=1.0, frequency_penalty=0.0, presence_penalty=0.0, n=1, best_of=1, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', batch_size=20, request_timeout=None, logit_bias={}, max_retries=6, streaming=False, allowed_special=set(), disallowed_special='all', tiktoken_model_name=None)"
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:07:35.025420900Z",
     "start_time": "2023-08-24T12:07:34.981555200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "data": {
      "text/plain": "OpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, client=<class 'openai.api_resources.completion.Completion'>, model_name='text-davinci-003', temperature=0.7, max_tokens=256, top_p=1.0, frequency_penalty=0.0, presence_penalty=0.0, n=1, best_of=1, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', batch_size=20, request_timeout=None, logit_bias={}, max_retries=6, streaming=False, allowed_special=set(), disallowed_special='all', tiktoken_model_name=None)"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm = load_llm(\"llmstore/llm.yaml\")\n",
    "llm"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:07:58.286760100Z",
     "start_time": "2023-08-24T12:07:58.263762200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Saving\n",
    "如果要从内存中的 LLM 转到它的序列化版本，可以通过调用该方法 .save 轻松完成。同样，这同时支持 json 和 yaml。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [],
   "source": [
    "llm.save(\"llmsave.json\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:09:05.792130700Z",
     "start_time": "2023-08-24T12:09:05.784132300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [],
   "source": [
    "llm.save(\"llmsave.yaml\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:09:16.473454400Z",
     "start_time": "2023-08-24T12:09:16.442452Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.7 大语言模型的流式处理响应\n",
    "某些 LLM 提供流式处理响应。这意味着，您可以在响应可用时立即开始处理它，而不是等待整个响应返回。\n",
    "\n",
    "如果要在生成响应时向用户显示响应，或者要在生成响应时处理响应，这将非常有用。\n",
    "\n",
    "目前，我们支持各种 LLM 实现的流式处理，包括但不限于 OpenAI 、 ChatOpenAI ChatAnthropic Hugging Face Text Generation Inference 和 Replicate 。\n",
    "\n",
    "此功能已扩展为适应大多数型号。要利用流式处理，请使用 CallbackHandler 实现 on_llm_new_token .在此示例中，我们使用 StreamingStdOutCallbackHandler ."
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Verse 1\n",
      "I'm sippin' on sparkling water,\n",
      "It's so refreshing and light,\n",
      "It's the perfect way to quench my thirst\n",
      "On a hot summer night.\n",
      "\n",
      "Chorus\n",
      "Sparkling water, sparkling water,\n",
      "It's the best way to stay hydrated,\n",
      "It's so crisp and so clean,\n",
      "It's the perfect way to stay refreshed.\n",
      "\n",
      "Verse 2\n",
      "I'm sippin' on sparkling water,\n",
      "It's so bubbly and bright,\n",
      "It's the perfect way to cool me down\n",
      "On a hot summer night.\n",
      "\n",
      "Chorus\n",
      "Sparkling water, sparkling water,\n",
      "It's the best way to stay hydrated,\n",
      "It's so crisp and so clean,\n",
      "It's the perfect way to stay refreshed.\n",
      "\n",
      "Verse 3\n",
      "I'm sippin' on sparkling water,\n",
      "It's so light and so clear,\n",
      "It's the perfect way to keep me cool\n",
      "On a hot summer night.\n",
      "\n",
      "Chorus\n",
      "Sparkling water, sparkling water,\n",
      "It's the best way to stay hydrated,\n",
      "It's so crisp and so clean,\n",
      "It's the perfect way to stay refreshed."
     ]
    }
   ],
   "source": [
    "from langchain.llms import OpenAI\n",
    "from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
    "\n",
    "\n",
    "llm = OpenAI(streaming=True, callbacks=[StreamingStdOutCallbackHandler()], temperature=0)\n",
    "resp = llm(\"Write me a song about sparkling water.\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T15:13:55.687133100Z",
     "start_time": "2023-08-24T15:13:48.830926300Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "我们仍然可以通过使用generate来访问最终的LLMResult。然而，目前不支持在流式处理中使用token_usage。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Q: What did the fish say when it hit the wall?\n",
      "A: Dam!"
     ]
    },
    {
     "data": {
      "text/plain": "LLMResult(generations=[[Generation(text='\\n\\nQ: What did the fish say when it hit the wall?\\nA: Dam!', generation_info={'finish_reason': 'stop', 'logprobs': None})]], llm_output={'token_usage': {}, 'model_name': 'text-davinci-003'}, run=[RunInfo(run_id=UUID('c47c9b6f-07b2-4769-baf6-f93916b80077'))])"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm.generate([\"Tell me a joke.\"])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T15:14:20.132051900Z",
     "start_time": "2023-08-24T15:14:17.237331700Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.8 大语言模型的跟踪令牌使用情况\n",
    "LangChain提供了一个方便的方法，用于跟踪LLM的令牌使用情况。这对于调试或教育目的非常有用。\n",
    "仅适用于OpenAI API。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tokens Used: 346\n",
      "\tPrompt Tokens: 10\n",
      "\tCompletion Tokens: 336\n",
      "Successful Requests: 1\n",
      "Total Cost (USD): $0.00692\n"
     ]
    }
   ],
   "source": [
    "from langchain.llms import OpenAI\n",
    "from langchain.callbacks import get_openai_callback\n",
    "llm = OpenAI(model_name=\"text-davinci-002\", n=2, best_of=2,cache = None)\n",
    "\n",
    "with get_openai_callback() as cb:\n",
    "    result = llm(\"讲个笑话\")\n",
    "    print(cb)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:23:05.708974900Z",
     "start_time": "2023-08-24T12:22:57.978220800Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "上下文管理器中的任何内容都将被跟踪。下面是使用它按顺序跟踪多个调用的示例。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tokens Used: 530\n",
      "\tPrompt Tokens: 30\n",
      "\tCompletion Tokens: 500\n",
      "Successful Requests: 2\n",
      "Total Cost (USD): $0.010600000000000002\n"
     ]
    }
   ],
   "source": [
    "with get_openai_callback() as cb:\n",
    "    result2 = llm(\"给我讲个笑话\")\n",
    "    result3 = llm(\"给我讲个笑话\")\n",
    "    print(cb)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:23:16.039582700Z",
     "start_time": "2023-08-24T12:23:09.511757500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果使用具有多个步骤的链或代理，它将跟踪所有这些步骤。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m I need to find out when she was born.\n",
      "Action: Calculator\n",
      "Action Input: 2020 - 1957\u001B[0m\n",
      "Observation: \u001B[36;1m\u001B[1;3mAnswer: 63\u001B[0m\n",
      "Thought:\u001B[32;1m\u001B[1;3m I now know the final answer\n",
      "Final Answer: 王菲现在的年龄是63岁。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "Total Tokens: 681\n",
      "Prompt Tokens: 606\n",
      "Completion Tokens: 75\n",
      "Total Cost (USD): $0.01362\n"
     ]
    }
   ],
   "source": [
    "from langchain.agents import load_tools\n",
    "from langchain.agents import initialize_agent\n",
    "from langchain.agents import AgentType\n",
    "from langchain.llms import OpenAI\n",
    "\n",
    "llm = OpenAI(temperature=0)\n",
    "tools = load_tools([\"llm-math\"], llm=llm)\n",
    "agent = initialize_agent(\n",
    "    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
    ")\n",
    "with get_openai_callback() as cb:\n",
    "    response = agent.run(\n",
    "        \"王菲现在的年龄是多少？\"\n",
    "    )\n",
    "    print(f\"Total Tokens: {cb.total_tokens}\")\n",
    "    print(f\"Prompt Tokens: {cb.prompt_tokens}\")\n",
    "    print(f\"Completion Tokens: {cb.completion_tokens}\")\n",
    "    print(f\"Total Cost (USD): ${cb.total_cost}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-08-24T12:25:31.984056100Z",
     "start_time": "2023-08-24T12:25:27.680248Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
